package com.example.zgdemo.aop;

import org.apache.commons.io.IOUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ResponseStatusException;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;


@Aspect
@Component
public class RateLimitAspect {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private  String LUA_SCRIPT ="";

    public RateLimitAspect(ResourceLoader resourceLoader) throws IOException {
        this.resourceLoader = resourceLoader;
        LUA_SCRIPT = loadLuaScript();
    }

    @Autowired
    private ResourceLoader resourceLoader;

    public String loadLuaScript() throws IOException {
        Resource resource = resourceLoader.getResource("classpath:scripts/leaky_bucket.lua");
        return IOUtils.toString(resource.getInputStream(), StandardCharsets.UTF_8);
    }
    @Around("@annotation(rateLimit)")
    public Object around(ProceedingJoinPoint joinPoint, RateLimit rateLimit) throws Throwable {
        // 构造限流 key
        String key = rateLimit.value();

        // 获取注解参数
        int capacity = rateLimit.capacity();
        int rate = rateLimit.rate();

        // 生成当前时间戳 (毫秒)
        long now = System.currentTimeMillis();

        // 执行 Lua 脚本
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(LUA_SCRIPT, Long.class);
        List<String> keys = Collections.singletonList(key);
        Long result = redisTemplate.execute(
                redisScript,
                keys,
                String.valueOf(capacity),
                String.valueOf(rate),
                String.valueOf(now)
        );

        // 处理限流结果
        if (result == 0) {
            throw new ResponseStatusException(HttpStatus.TOO_MANY_REQUESTS, "请求过于频繁");
        }

        return joinPoint.proceed();
    }
}
